package bancosys.tec.persist.validator;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import jmine.tec.utils.debug.impl.DebugRuntimeFactory;
import jmine.tec.utils.reflection.UnmodifiableChecker;
import jmine.tec.utils.register.Receiver;
import bancosys.tec.persist.Persistable;

/**
 * @author Fabio Sakiyama
 * @created 26/04/2011
 */
public class ValidatorRegistry implements Receiver<Validator<?>> {

    private final Map<Class<?>, Set<? extends Validator<?>>> validatorsByType =
            new ConcurrentHashMap<Class<?>, Set<? extends Validator<?>>>();

    private List<Validator<? extends Persistable>> listaValidator = new ArrayList<Validator<? extends Persistable>>();

    /**
     * Registra os validators que serão obtidos na criacao do Persister.
     * 
     * @param listValidator Lista de validators que serão injetados via spring.
     */
    public void register(Collection<? extends Validator<?>> listValidator) {
        if (DebugRuntimeFactory.ENABLED) {
            for (Validator<?> validator : listValidator) {
                if (!UnmodifiableChecker.isUnmodifiableAnnotationPresent(validator.getClass())) {
                    System.err.println("Validator of type " + validator.getClass() + " is not @Unmodifiable!");
                }
            }
        }
        this.listaValidator.addAll(listValidator);

    }

    /**
     * Obtem a lista de validators que devem ser utilizados para persistir um bean.
     * 
     * @param persistableClass persistableClass
     * @param <T> classe do bean.
     * @return lista contendo os validators que devem ser utilizados para persistir um bean
     */
    @SuppressWarnings("unchecked")
    public <T extends Persistable> Set<Validator<T>> getValidators(Class<T> persistableClass) {
        // Verifica se já existe, para não carregar novamente
        Set<Validator<T>> set = (Set<Validator<T>>) this.validatorsByType.get(persistableClass);
        if (set != null) {
            return set;
        }
        Set<Validator<T>> validators = new LinkedHashSet<Validator<T>>();

        for (Validator<?> validator : this.getListaValidator()) {
            if (validator.getTargetClass().isAssignableFrom(persistableClass)) {
                validators.add((Validator<T>) validator);
            }
        }
        this.validatorsByType.put(persistableClass, validators);
        return validators;

    }

    /**
     * @return the listaValidator
     */
    public List<Validator<? extends Persistable>> getListaValidator() {
        return this.listaValidator;
    }

    /**
     * @param listaValidator the listaValidator to set
     */
    public void setListaValidator(List<Validator<? extends Persistable>> listaValidator) {
        this.listaValidator = listaValidator;
    }

}
